#include <ostream>
#include "Server.h"
#include "..\SharedMethods\globals.h"



using std::ostringstream;

Server::Server(int port)
{
	portNumber = port;
}

bool Server::run()
{
	SOCKET 		hSocket = INVALID_SOCKET,
				hClientSocket = INVALID_SOCKET;
	bool		bSuccess = true;
	sockaddr_in	sockAddr = {0};
	
	WSADATA wsadata;
	char localhost[30];
	HOSTENT *hp;

	try
	{

			if (WSAStartup(0x0202,&wsadata)!=0)
			{  
				throw "Error in starting WSAStartup()\n";
			}
			else
			{
			//	buffer="WSAStartup was successful\n";   
			//	WriteFile(test,buffer,sizeof(buffer),&dwtest,NULL); 

				/* display the wsadata structure */
				cout<< endl
					<< "wsadata.wVersion "       << wsadata.wVersion       << endl
					<< "wsadata.wHighVersion "   << wsadata.wHighVersion   << endl
					<< "wsadata.szDescription "  << wsadata.szDescription  << endl
					<< "wsadata.szSystemStatus " << wsadata.szSystemStatus << endl
					<< "wsadata.iMaxSockets "    << wsadata.iMaxSockets    << endl
					<< "wsadata.iMaxUdpDg "      << wsadata.iMaxUdpDg      << endl;
			}  

			//Display info of local host

			gethostname(localhost,10);
			cout<<"hostname: "<<localhost<< endl;

			if((hp=gethostbyname(localhost)) == NULL) 
			{
				throw "gethostbyname() cannot get local host info?"; 
			}
			
		// Create socket
		cout << "Creating socket... ";
		if ((hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET)
			throw "could not create socket.";
		cout << "created.\n";
		
		// Bind socket
		cout << "Binding socket... ";
		
		SetServerSockAddr(&sockAddr, portNumber);

		if (bind(hSocket, reinterpret_cast<sockaddr*>(&sockAddr), sizeof(sockAddr)) != 0)
			throw "could not bind socket.";
		cout << "bound.\n";

		// Put socket in listening mode
		cout << "Putting socket in listening mode... ";
		if (listen(hSocket, SOMAXCONN)!=0)
			throw "could not put socket in listening mode.";
		cout << "done.\n";
	}
	catch(char* ex)
	{
		cerr << "\nError: " << ex << endl;
		bSuccess = false; 
	}

	//if (hSocket!=INVALID_SOCKET)
	//	closesocket(hSocket);
	//
	//if (hClientSocket!=INVALID_SOCKET)
	//	closesocket(hClientSocket);

		while(true)
		{
			try
			{
				// Wait for connection
				cout << "Waiting for incoming connection... ";
		
				sockaddr_in clientSockAddr;
				int			clientSockSize = sizeof(clientSockAddr);
		
				// Accept connection:
				hClientSocket = accept(hSocket,
								 reinterpret_cast<sockaddr*>(&clientSockAddr),
								 &clientSockSize);
	
				// Check if accept succeeded
				if (hClientSocket==INVALID_SOCKET)
					throw "accept function failed.";
				cout << "accepted connection from: " << GetHostDescription(clientSockAddr) << endl;

				//start a client thread, to handle requests from this client.
				ClientThread* pThread = new ClientThread(hClientSocket, clientSockAddr);
				pThread->start(); 
			}
			catch(char* ex)
			{
				cerr << "\nError: " << ex << endl;
				bSuccess = false; 
			}

		}
		// Wait for and accept a connection:
		//HandleConnection(hClientSocket, clientSockAddr);
		
	return bSuccess;
	
}


void Server::SetServerSockAddr(sockaddr_in *pSockAddr, int portNumber)
{
	// Set family, port and find IP
	pSockAddr->sin_family = AF_INET;
	pSockAddr->sin_port = htons(portNumber);
	pSockAddr->sin_addr.S_un.S_addr = INADDR_ANY;
}



